package com.xiaoshuidi.cloud.module.rooms.job.xxljob;

import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xiaoshuidi.cloud.framework.common.exception.ErrorCode;
import com.xiaoshuidi.cloud.framework.common.exception.ServiceException;
import com.xiaoshuidi.cloud.framework.common.util.json.JsonUtils;
import com.xiaoshuidi.cloud.framework.tenant.core.aop.TenantIgnore;
import com.xiaoshuidi.cloud.framework.tenant.core.context.TenantContextHolder;
import com.xiaoshuidi.cloud.framework.tenant.core.job.TenantJob;
import com.xiaoshuidi.cloud.module.contract.api.ContractApi;
import com.xiaoshuidi.cloud.module.contract.vo.ContractRoommateApiVO;
import com.xiaoshuidi.cloud.module.contract.vo.RoomContractApiRespVO;
import com.xiaoshuidi.cloud.module.rooms.api.roomstate.dto.LivingWithInfoDTO;
import com.xiaoshuidi.cloud.module.rooms.api.roomstate.dto.RoomContractInfoDTO;
import com.xiaoshuidi.cloud.module.rooms.api.roomstate.dto.RoomTenantsInfoDTO;
import com.xiaoshuidi.cloud.module.rooms.controller.admin.roomel.vo.RoomelCreateReqVO;
import com.xiaoshuidi.cloud.module.rooms.convert.roomel.MyRoomelConvert;
import com.xiaoshuidi.cloud.module.rooms.enums.RentStatusEnum;
import com.xiaoshuidi.cloud.module.rooms.pojo.*;
import com.xiaoshuidi.cloud.module.rooms.pojo.roomel.RoomelEntity;
import com.xiaoshuidi.cloud.module.rooms.repository.*;
import com.xiaoshuidi.cloud.module.rooms.service.RoomStateRecordService;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import static com.xiaoshuidi.cloud.module.rooms.enums.ApiConstants.ROOMELENTIRY;

/**
 * 房源Es索引重建后,数据同步任务
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class RoomEsRebuildJob {

    private static final Integer pageSize = 1000;

    private final RoomHouseRepository roomHouseRepository;
    private final ApartmentRepository apartmentRepository;
    private final RoomApartmentAreaRepository roomApartmentAreaRepository;
    private final RoomAreaRepository roomAreaRepository;
    private final RoomHouseTypeRepository roomHouseTypeRepository;
    private final RoomLayoutRepository roomLayoutRepository;
    private final RestHighLevelClient restHighLevelClient;
    private final RoomStateRecordRepository roomStateRecordRepository;
    private final RoomHouseFilingsRepository roomHouseFilingsRepository;
    private final ContractApi contractApi;
    private final RoomStateRecordService roomStateRecordService;

    @XxlJob("rebuild-rooms-es-index")
    @TenantIgnore
    public void rebuildRoomsEsIndex(Long param) {
        log.info("---------------重建房源es索引任务执行-------------");

        // 检查是否存在fy_roomel索引, 若不存在, 则先创建索引
        this.checkIndex();

        String jobParam = XxlJobHelper.getJobParam();
        Long tenantId = null;
        Long id = null;

        if (ObjectUtil.isNotEmpty(jobParam)) {
            String[] split = jobParam.split(",");
            if (ObjectUtil.isNotEmpty(split[0])) {
                tenantId = Long.valueOf(split[0]);
            }
            if (split.length > 1) {
                id = Long.valueOf(split[1]);
            }
        }

        if(ObjectUtil.isNotEmpty(param)){
            id = param;
        }

        LambdaQueryWrapper<RoomHouse> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(ObjectUtil.isNotEmpty(tenantId), RoomHouse::getTenantId, tenantId);
        wrapper.eq(ObjectUtil.isNotEmpty(id), RoomHouse::getId, id);
        long count = roomHouseRepository.count(wrapper);
        // 循环次数
        long loopNum = count / pageSize + (count % pageSize > 0 ? 1 : 0);
        CountDownLatch countDownLatch = new CountDownLatch((int) loopNum);
        for (long l = 1; l <= loopNum; l++) {
            long finalL = l;
            ThreadUtil.execAsync(new Runnable() {
                @Override
                public void run() {
                    log.info("---------------重建房源es索引,线程:{},第{}页-------------", Thread.currentThread().getName(), finalL);
                    try {
                        TenantContextHolder.setIgnore(true);
                        // 每次处理1000条数据
                        List<RoomHouse> roomHouses = roomHouseRepository.page(new Page<>(finalL, pageSize), wrapper).getRecords();
                        List<RoomelCreateReqVO> roomelCreateReqVOS = new ArrayList<>();

                        roomHouses.stream().forEach(roomHouse -> {
                            TenantContextHolder.setTenantId(roomHouse.getTenantId());
                            // 组装ES所需数据
                            Apartment apartment = null;
                            RoomApartmentArea roomApartmentArea = null;
                            RoomArea roomArea = null;
                            RoomHouseType roomHouseType = null;
                            RoomStateRecord roomStateRecord = null;
                            RoomHouseFilings roomHouseFilings = null;
                            List<ContractRoommateApiVO> contractRoommateApiVOS = new ArrayList<>();
                            RoomContractApiRespVO roomContractApiRespVO = null;
                            RoomContractApiRespVO renewalContract = null;
                            try {
                                apartment = apartmentRepository.myGetById(roomHouse.getApartmentId());
                                roomApartmentArea = roomApartmentAreaRepository.myGetById(roomHouse.getApartmentAreaId());
                                roomArea = roomAreaRepository.myGetById(roomApartmentArea.getRoomAreaId());
                                roomHouseType = roomHouseTypeRepository.myGetById(roomHouse.getRoomHouseTypeId());
                                roomStateRecord = roomStateRecordService.getByRoomIdAndIsCurrentState(roomHouse.getId());
                                roomHouseFilings = roomHouseFilingsRepository.getByRoomHouseId(roomHouse.getId());
                                contractRoommateApiVOS = contractApi.getRoommateByRoomId(roomHouse.getId()).getCheckedData();
                                //查当前合同
                                roomContractApiRespVO = contractApi.getContractByRoomId(roomHouse.getId()).getCheckedData();
                                if (ObjectUtil.isNotEmpty(roomContractApiRespVO)) {
                                    // 查续租合同
                                    renewalContract = contractApi.getRenewalContractByContractId(roomContractApiRespVO.getId()).getCheckedData();
                                }
                                log.info("房源:{},租住人信息:{}", roomHouse.getId(), JsonUtils.toJsonString(contractRoommateApiVOS));
                                log.info("房源:{},当前合同:{}", roomHouse.getId(), JsonUtils.toJsonString(roomContractApiRespVO));
                                log.info("房源:{},续租合同:{}", roomHouse.getId(), JsonUtils.toJsonString(renewalContract));
                            } catch (Exception e) {
                                log.error("重建房源es索引任务异常,roomHouseId:" + roomHouse.getId(), e);
                                return;
                            }
                            StringBuilder sb = new StringBuilder();
                            sb.append(roomHouse.getArea());
                            sb.append(roomHouse.getBuildingNo());
                            sb.append("栋");
                            if (!roomHouse.getIsConcentrated()) {
                                sb.append(roomHouse.getUnitNo());
                                sb.append("单元");
                            }
                            sb.append(roomHouse.getName());
                            String fullName = sb.toString();
                            // 集中式
                            if (roomHouse.getIsConcentrated()) {
                                RoomLayout roomLayout = roomLayoutRepository.myGetById(roomHouse.getLayoutId());
                                RoomelCreateReqVO roomelCreateReqVO = new RoomelCreateReqVO();
                                roomelCreateReqVO.setId(roomHouse.getId());
                                roomelCreateReqVO.setIsStop(roomHouse.getIsStop());
                                roomelCreateReqVO.setFullName(fullName);
                                roomelCreateReqVO.setSuperId(roomHouse.getSuperId());
                                roomelCreateReqVO.setApartmentAreaId(roomApartmentArea.getId());
                                roomelCreateReqVO.setApartmentAreaName(roomApartmentArea.getArea());
                                roomelCreateReqVO.setApartmentName(apartment.getName());
                                roomelCreateReqVO.setApartmentId(apartment.getId());
                                roomelCreateReqVO.setIsConcentrated(roomHouse.getIsConcentrated());
                                roomelCreateReqVO.setApartmentAreaLat(roomArea.getGeoLat());
                                roomelCreateReqVO.setApartmentAreaLon(roomArea.getGeoLng());
                                roomelCreateReqVO.setApartmentLat(apartment.getLatitude());
                                roomelCreateReqVO.setApartmentLon(apartment.getLongitude());
                                roomelCreateReqVO.setSourceType(apartment.getSourceType());
                                roomelCreateReqVO.setFloorId(roomHouse.getFloorId());
                                roomelCreateReqVO.setBuildingNo(roomHouse.getBuildingNo());
                                roomelCreateReqVO.setUnitNo(roomHouse.getUnitNo());
                                roomelCreateReqVO.setFloorNo(Integer.valueOf(roomHouse.getFloorNo()));
                                roomelCreateReqVO.setFloorSum(roomApartmentArea.getFloorNum());
                                roomelCreateReqVO.setCity(roomApartmentArea.getCity());
                                roomelCreateReqVO.setDistrict(roomApartmentArea.getDistrict());
                                roomelCreateReqVO.setStreet(roomApartmentArea.getStreet());
                                roomelCreateReqVO.setAddress(roomApartmentArea.getAddress());
                                roomelCreateReqVO.setBedroomNum(roomHouseType.getBedRoomNum());
                                roomelCreateReqVO.setLivingroomNum(roomHouseType.getLivingRoomNum());
                                roomelCreateReqVO.setKitchenNum(roomHouseType.getKitchenNum());
                                roomelCreateReqVO.setToiletNum(roomHouseType.getToiletNum());
                                roomelCreateReqVO.setBalcony(roomHouseType.getBalcony());
                                roomelCreateReqVO.setRoomHouseTypeId(roomLayout.getRoomHouseTypeId());
                                roomelCreateReqVO.setRoomHouseTypeName(roomHouseType.getName());
                                roomelCreateReqVO.setLayoutId(roomLayout.getId());
                                roomelCreateReqVO.setLayoutName(roomLayout.getName());
                                roomelCreateReqVO.setFacetoType(roomHouse.getToward());
                                roomelCreateReqVO.setIsWhole(roomHouse.getIsWhole());
                                roomelCreateReqVO.setSpace(roomHouse.getSpace());
                                roomelCreateReqVO.setDecoration(roomHouse.getDecoration());
                                roomelCreateReqVO.setHouseState(RentStatusEnum.EMPTY.getValue());
                                roomelCreateReqVO.setRoomHouseName(roomHouse.getName());
                                roomelCreateReqVO.setIsScheduled(false);
                                roomelCreateReqVO.setTenantId(roomHouse.getTenantId());
                                roomelCreateReqVO.setRoomHouseNo(roomHouse.getNo());
                                roomelCreateReqVO.setHouseNo(roomHouse.getHouseNo());
                                roomelCreateReqVO.setIsLock(roomHouse.getIsLock());
                                roomelCreateReqVO.setPublicFacilities(roomHouse.getPublicFacilities());
                                roomelCreateReqVO.setPrice(roomHouse.getMonthRental());
                                roomelCreateReqVO.setCreateTime(roomHouse.getCreateTime());
                                roomelCreateReqVO.setDeptId(roomHouse.getDeptId());
                                roomelCreateReqVO.setRoomUsage(roomHouse.getRoomUsage());
                                roomelCreateReqVO.setRoomAreaId(roomApartmentArea.getRoomAreaId());
                                roomelCreateReqVO.setHouseState(ObjectUtil.isEmpty(roomStateRecord) ? RentStatusEnum.EMPTY.getValue() : roomStateRecord.getState());
                                roomelCreateReqVO.setCheckCode(ObjectUtil.isNotEmpty(roomHouseFilings) ? roomHouseFilings.getCheckCode() : null);
                                roomelCreateReqVO.setCheckCodeInDate(ObjectUtil.isNotEmpty(roomHouseFilings) ? roomHouseFilings.getCheckCodeInDate() : null);
                                roomelCreateReqVO.setIsClean(roomHouse.getIsClean());
                                roomelCreateReqVO.setIsRepair(roomHouse.getIsRepair());
                                // 封装租客信息
                                tenantInfo(contractRoommateApiVOS, roomelCreateReqVO);
                                contractInfo(roomContractApiRespVO, renewalContract, roomelCreateReqVO);
                                roomelCreateReqVOS.add(roomelCreateReqVO);
                            } else {
                                // 分散式
                                // 整租 或者 合租的主房间
                                if (roomHouse.getIsWhole() || (!roomHouse.getIsWhole() && ObjectUtil.isEmpty(roomHouse.getSuperId()))) {
                                    // 组装主房间ES所需数据
                                    RoomelCreateReqVO masterRoomelCreateReqVO = new RoomelCreateReqVO();
                                    masterRoomelCreateReqVO.setId(roomHouse.getId());
                                    masterRoomelCreateReqVO.setIsStop(roomHouse.getIsStop());
                                    masterRoomelCreateReqVO.setFullName(fullName);
                                    masterRoomelCreateReqVO.setApartmentAreaId(roomApartmentArea.getId());
                                    masterRoomelCreateReqVO.setApartmentAreaName(roomApartmentArea.getArea());
                                    masterRoomelCreateReqVO.setApartmentName(apartment.getName());
                                    masterRoomelCreateReqVO.setApartmentId(apartment.getId());
                                    masterRoomelCreateReqVO.setIsConcentrated(roomApartmentArea.getIsConcentrated());
                                    masterRoomelCreateReqVO.setApartmentAreaLat(roomArea.getGeoLat());
                                    masterRoomelCreateReqVO.setApartmentAreaLon(roomArea.getGeoLng());
                                    masterRoomelCreateReqVO.setApartmentLat(apartment.getLatitude());
                                    masterRoomelCreateReqVO.setApartmentLon(apartment.getLongitude());
                                    masterRoomelCreateReqVO.setSourceType(apartment.getSourceType());
                                    masterRoomelCreateReqVO.setFloorId(roomHouse.getFloorId());
                                    masterRoomelCreateReqVO.setBuildingNo(roomHouse.getBuildingNo());
                                    masterRoomelCreateReqVO.setUnitNo(roomHouse.getUnitNo());
                                    masterRoomelCreateReqVO.setFloorNo(Integer.valueOf(roomHouse.getFloorNo()));
                                    masterRoomelCreateReqVO.setFloorSum(roomApartmentArea.getFloorNum());
                                    masterRoomelCreateReqVO.setCity(roomApartmentArea.getCity());
                                    masterRoomelCreateReqVO.setDistrict(roomApartmentArea.getDistrict());
                                    masterRoomelCreateReqVO.setStreet(roomApartmentArea.getStreet());
                                    masterRoomelCreateReqVO.setAddress(roomApartmentArea.getAddress());
                                    masterRoomelCreateReqVO.setBedroomNum(roomHouseType.getBedRoomNum());
                                    masterRoomelCreateReqVO.setLivingroomNum(roomHouseType.getLivingRoomNum());
                                    masterRoomelCreateReqVO.setKitchenNum(roomHouseType.getKitchenNum());
                                    masterRoomelCreateReqVO.setToiletNum(roomHouseType.getToiletNum());
                                    masterRoomelCreateReqVO.setBalcony(roomHouseType.getBalcony());
                                    masterRoomelCreateReqVO.setRoomHouseTypeId(roomHouseType.getId());
                                    masterRoomelCreateReqVO.setRoomHouseTypeName(roomHouseType.getName());
                                    masterRoomelCreateReqVO.setFacetoType(roomHouse.getToward());
                                    masterRoomelCreateReqVO.setIsWhole(roomHouse.getIsWhole());
                                    masterRoomelCreateReqVO.setSpace(roomHouse.getSpace());
                                    masterRoomelCreateReqVO.setDecoration(roomHouse.getDecoration());
                                    masterRoomelCreateReqVO.setHouseState(RentStatusEnum.EMPTY.getValue());
                                    masterRoomelCreateReqVO.setRoomHouseName(roomHouse.getName());
                                    masterRoomelCreateReqVO.setIsScheduled(false);
                                    masterRoomelCreateReqVO.setTenantId(roomHouse.getTenantId());
                                    masterRoomelCreateReqVO.setRoomHouseNo(roomHouse.getNo());
                                    masterRoomelCreateReqVO.setHouseNo(roomHouse.getHouseNo());
                                    masterRoomelCreateReqVO.setIsLock(roomHouse.getIsLock());
                                    masterRoomelCreateReqVO.setPublicFacilities(roomHouse.getPublicFacilities());
                                    masterRoomelCreateReqVO.setCreateTime(roomHouse.getCreateTime());
                                    masterRoomelCreateReqVO.setPrice(roomHouse.getMonthRental());
                                    masterRoomelCreateReqVO.setDeptId(roomHouse.getDeptId());
                                    masterRoomelCreateReqVO.setRoomUsage(roomHouse.getRoomUsage());
                                    masterRoomelCreateReqVO.setRoomAreaId(roomApartmentArea.getRoomAreaId());
                                    masterRoomelCreateReqVO.setHouseState(ObjectUtil.isEmpty(roomStateRecord) ? RentStatusEnum.EMPTY.getValue() : roomStateRecord.getState());
                                    masterRoomelCreateReqVO.setCheckCode(ObjectUtil.isNotEmpty(roomHouseFilings) ? roomHouseFilings.getCheckCode() : null);
                                    masterRoomelCreateReqVO.setCheckCodeInDate(ObjectUtil.isNotEmpty(roomHouseFilings) ? roomHouseFilings.getCheckCodeInDate() : null);
                                    masterRoomelCreateReqVO.setIsClean(roomHouse.getIsClean());
                                    masterRoomelCreateReqVO.setIsRepair(roomHouse.getIsRepair());
                                    // 封装租客信息
                                    tenantInfo(contractRoommateApiVOS, masterRoomelCreateReqVO);
                                    contractInfo(roomContractApiRespVO, renewalContract, masterRoomelCreateReqVO);
                                    roomelCreateReqVOS.add(masterRoomelCreateReqVO);
                                } else {
                                    // 合租 子房间
                                    RoomelCreateReqVO roomelCreateReqVO = new RoomelCreateReqVO();
                                    roomelCreateReqVO.setId(roomHouse.getId());
                                    roomelCreateReqVO.setIsStop(roomHouse.getIsStop());
                                    roomelCreateReqVO.setFullName(fullName);
                                    roomelCreateReqVO.setSuperId(roomHouse.getSuperId());
                                    roomelCreateReqVO.setApartmentAreaId(roomApartmentArea.getId());
                                    roomelCreateReqVO.setApartmentAreaName(roomApartmentArea.getArea());
                                    roomelCreateReqVO.setApartmentName(apartment.getName());
                                    roomelCreateReqVO.setApartmentId(apartment.getId());
                                    roomelCreateReqVO.setIsConcentrated(roomApartmentArea.getIsConcentrated());
                                    roomelCreateReqVO.setApartmentAreaLat(roomArea.getGeoLat());
                                    roomelCreateReqVO.setApartmentAreaLon(roomArea.getGeoLng());
                                    roomelCreateReqVO.setApartmentLat(apartment.getLatitude());
                                    roomelCreateReqVO.setApartmentLon(apartment.getLongitude());
                                    roomelCreateReqVO.setSourceType(apartment.getSourceType());
                                    roomelCreateReqVO.setFloorId(roomHouse.getFloorId());
                                    roomelCreateReqVO.setBuildingNo(roomHouse.getBuildingNo());
                                    roomelCreateReqVO.setUnitNo(roomHouse.getUnitNo());
                                    roomelCreateReqVO.setFloorNo(Integer.valueOf(roomHouse.getFloorNo()));
                                    roomelCreateReqVO.setFloorSum(roomApartmentArea.getFloorNum());
                                    roomelCreateReqVO.setCity(roomApartmentArea.getCity());
                                    roomelCreateReqVO.setDistrict(roomApartmentArea.getDistrict());
                                    roomelCreateReqVO.setStreet(roomApartmentArea.getStreet());
                                    roomelCreateReqVO.setAddress(roomApartmentArea.getAddress());
                                    roomelCreateReqVO.setBedroomNum(roomHouseType.getBedRoomNum());
                                    roomelCreateReqVO.setLivingroomNum(roomHouseType.getLivingRoomNum());
                                    roomelCreateReqVO.setKitchenNum(roomHouseType.getKitchenNum());
                                    roomelCreateReqVO.setToiletNum(roomHouseType.getToiletNum());
                                    roomelCreateReqVO.setBalcony(roomHouseType.getBalcony());
                                    roomelCreateReqVO.setRoomHouseTypeId(roomHouseType.getId());
                                    roomelCreateReqVO.setRoomHouseTypeName(roomHouseType.getName());
                                    roomelCreateReqVO.setFacetoType(roomHouse.getToward());
                                    roomelCreateReqVO.setIsWhole(roomHouse.getIsWhole());
                                    roomelCreateReqVO.setSpace(roomHouse.getSpace());
                                    roomelCreateReqVO.setDecoration(roomHouse.getDecoration());
                                    roomelCreateReqVO.setHouseState(RentStatusEnum.EMPTY.getValue());
                                    roomelCreateReqVO.setRoomHouseName(roomHouse.getName());
                                    roomelCreateReqVO.setIsScheduled(false);
                                    roomelCreateReqVO.setTenantId(roomHouse.getTenantId());
                                    roomelCreateReqVO.setRoomHouseNo(roomHouse.getNo());
                                    roomelCreateReqVO.setHouseNo(roomHouse.getHouseNo());
                                    roomelCreateReqVO.setIsLock(roomHouse.getIsLock());
                                    roomelCreateReqVO.setPublicFacilities(roomHouse.getPublicFacilities());
                                    roomelCreateReqVO.setCreateTime(roomHouse.getCreateTime());
                                    roomelCreateReqVO.setDeptId(roomHouse.getDeptId());
                                    roomelCreateReqVO.setPrice(roomHouse.getMonthRental());
                                    roomelCreateReqVO.setRoomType(roomHouse.getRoomType());
                                    roomelCreateReqVO.setRoomUsage(roomHouse.getRoomUsage());
                                    roomelCreateReqVO.setRoomAreaId(roomApartmentArea.getRoomAreaId());
                                    roomelCreateReqVO.setHouseState(ObjectUtil.isEmpty(roomStateRecord) ? RentStatusEnum.EMPTY.getValue() : roomStateRecord.getState());
                                    roomelCreateReqVO.setCheckCode(ObjectUtil.isNotEmpty(roomHouseFilings) ? roomHouseFilings.getCheckCode() : null);
                                    roomelCreateReqVO.setCheckCodeInDate(ObjectUtil.isNotEmpty(roomHouseFilings) ? roomHouseFilings.getCheckCodeInDate() : null);
                                    roomelCreateReqVO.setIsClean(roomHouse.getIsClean());
                                    roomelCreateReqVO.setIsRepair(roomHouse.getIsRepair());
                                    // 封装租客信息
                                    tenantInfo(contractRoommateApiVOS, roomelCreateReqVO);
                                    contractInfo(roomContractApiRespVO, renewalContract, roomelCreateReqVO);
                                    roomelCreateReqVOS.add(roomelCreateReqVO);
                                }
                            }
                        });
                        // 推送房源信息到es
                        List<RoomelEntity> roomelEntityList = MyRoomelConvert.roomelCreateReqVOToRoomelEntity(roomelCreateReqVOS);
                        bulkPutIndex(roomelEntityList, ROOMELENTIRY);
                    } finally {
                        countDownLatch.countDown();
                        TenantContextHolder.setIgnore(false);
                    }
                }
            });
        }
        try {
            log.info("---------------重建房源es索引,等待子线程执行完成-------------");
            countDownLatch.await();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        log.info("---------------重建房源es索引任务完成-------------");
    }

    /**
     * 检查是否存在fy_roomel索引, 若不存在, 则先创建索引
     */
    private void checkIndex() {
        GetIndexRequest request = new GetIndexRequest(ROOMELENTIRY);
        try {
            boolean exists = restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);
            if (!exists) {
                // 创建索引
                log.info("房源索引不存在");
                CreateIndexRequest createRequest = new CreateIndexRequest(ROOMELENTIRY);
                createRequest.mapping(fyRoomelIndexMapping, XContentType.JSON);
                createRequest.setTimeout(TimeValue.timeValueMinutes(1));
                createRequest.setMasterTimeout(TimeValue.timeValueMinutes(1));
                CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(createRequest, RequestOptions.DEFAULT);
                log.info("房源索引创建结果:{}", JsonUtils.toJsonString(createIndexResponse));
            }
        } catch (IOException e) {
            log.error("房源索引创建异常", e);
            throw new RuntimeException(e);
        }
    }

    /**
     * 封装合同信息
     *
     * @param roomContractApiRespVO 当前合同信息
     * @param renewalContract       续租合同信息
     * @param roomelCreateReqVO
     */
    public void contractInfo(RoomContractApiRespVO roomContractApiRespVO, RoomContractApiRespVO renewalContract, RoomelCreateReqVO roomelCreateReqVO) {
        if (ObjectUtil.isEmpty(roomContractApiRespVO)) {
            return;
        }
        RoomContractInfoDTO roomContractInfoDTO = new RoomContractInfoDTO();
        roomContractInfoDTO.setContractId(roomContractApiRespVO.getId());
        roomContractInfoDTO.setExpiryDate(roomContractApiRespVO.getEndTime());
        if (ObjectUtil.isNotEmpty(renewalContract)) {
            roomContractInfoDTO.setLeaseRenewalContractId(renewalContract.getId());
            roomContractInfoDTO.setLeaseRenewalExpiryDate(renewalContract.getEndTime());
        }
        roomelCreateReqVO.setContractInfo(JsonUtils.toJsonString(roomContractInfoDTO));
    }

    /**
     * 封装租客信息
     *
     * @param contractRoommateApiVOS
     * @param roomelCreateReqVO
     */
    public void tenantInfo(List<ContractRoommateApiVO> contractRoommateApiVOS, RoomelCreateReqVO roomelCreateReqVO) {
        if (ObjectUtil.isEmpty(contractRoommateApiVOS)) {
            return;
        }
        List<LivingWithInfoDTO> livingWithInfoDTOS = new ArrayList<>();
        RoomTenantsInfoDTO roomTenantsInfoDTO = new RoomTenantsInfoDTO();
        contractRoommateApiVOS.stream().forEach(contractRoommateApiVO -> {
            // 同住人
            if (contractRoommateApiVO.getRoommateType().equals(0)) {
                LivingWithInfoDTO livingWithInfoDTO = new LivingWithInfoDTO();
                livingWithInfoDTO.setName(contractRoommateApiVO.getRoommateName());
                livingWithInfoDTO.setMobile(contractRoommateApiVO.getRoommatePhone());
                livingWithInfoDTOS.add(livingWithInfoDTO);
            } else if (contractRoommateApiVO.getRoommateType().equals(1)) {
                roomTenantsInfoDTO.setName(contractRoommateApiVO.getRoommateName());
                roomTenantsInfoDTO.setMobile(contractRoommateApiVO.getRoommatePhone());
                if (contractRoommateApiVO.getContractCustomerType().equals("company")) {
                    roomTenantsInfoDTO.setCompanyName(contractRoommateApiVO.getCompanyName());
                }
            }
        });
        roomTenantsInfoDTO.setLivingWithInfoDTOs(livingWithInfoDTOS);
        roomelCreateReqVO.setTenantinfo(JsonUtils.toJsonString(roomTenantsInfoDTO));
    }

    //批量插入
    private void bulkPutIndex(List<RoomelEntity> list, String index) {
        int size = list.size();
        BulkRequest request = new BulkRequest();
        for (int i = 0; i < size; i++) {
            RoomelEntity roomelEntity = list.get(i);
            IndexRequest indexRequest = new IndexRequest(index).id(String.valueOf(roomelEntity.getId())).source(JsonUtils.toJsonString(roomelEntity), XContentType.JSON);
            request.add(indexRequest);
        }
        try {
            restHighLevelClient.bulk(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            log.info("ES批量更新异常", e);
            throw new RuntimeException(e);
        }
    }

    /**
     * 房源索引结构
     */
    private static String fyRoomelIndexMapping = "{ \n" +
            "        \"properties\": {\n" +
            "            \"address\": {\n" +
            "                \"type\": \"text\",\n" +
            "                \"fields\": {\n" +
            "                    \"keyword\": {\n" +
            "                        \"type\": \"keyword\",\n" +
            "                        \"ignore_above\": 256\n" +
            "                    }\n" +
            "                },\n" +
            "                \"analyzer\": \"ik_max_word\",\n" +
            "                \"search_analyzer\": \"ik_smart\"\n" +
            "            },\n" +
            "            \"apartmentAreaGeo\": {\n" +
            "                \"type\": \"geo_point\"\n" +
            "            },\n" +
            "            \"apartmentAreaId\": {\n" +
            "                \"type\": \"long\"\n" +
            "            },\n" +
            "            \"apartmentAreaName\": {\n" +
            "                \"type\": \"text\",\n" +
            "                \"fields\": {\n" +
            "                    \"keyword\": {\n" +
            "                        \"type\": \"keyword\",\n" +
            "                        \"ignore_above\": 256\n" +
            "                    },\n" +
            "                    \"sort\": {\n" +
            "                        \"type\": \"icu_collation_keyword\",\n" +
            "                        \"index\": false,\n" +
            "                        \"language\": \"zh\",\n" +
            "                        \"country\": \"pinyin\"\n" +
            "                    }\n" +
            "                },\n" +
            "                \"analyzer\": \"ik_max_word\",\n" +
            "                \"search_analyzer\": \"ik_smart\"\n" +
            "            },\n" +
            "            \"apartmentGeo\": {\n" +
            "                \"type\": \"geo_point\"\n" +
            "            },\n" +
            "            \"apartmentId\": {\n" +
            "                \"type\": \"long\"\n" +
            "            },\n" +
            "            \"apartmentName\": {\n" +
            "                \"type\": \"text\",\n" +
            "                \"fields\": {\n" +
            "                    \"keyword\": {\n" +
            "                        \"type\": \"keyword\",\n" +
            "                        \"ignore_above\": 256\n" +
            "                    }\n" +
            "                },\n" +
            "                \"analyzer\": \"ik_max_word\",\n" +
            "                \"search_analyzer\": \"ik_smart\"\n" +
            "            },\n" +
            "            \"balcony\": {\n" +
            "                \"type\": \"long\"\n" +
            "            },\n" +
            "            \"bedroomNum\": {\n" +
            "                \"type\": \"long\"\n" +
            "            },\n" +
            "            \"billInfo\": {\n" +
            "                \"type\": \"text\",\n" +
            "                \"fields\": {\n" +
            "                    \"keyword\": {\n" +
            "                        \"type\": \"keyword\",\n" +
            "                        \"ignore_above\": 256\n" +
            "                    }\n" +
            "                },\n" +
            "                \"analyzer\": \"ik_max_word\",\n" +
            "                \"search_analyzer\": \"ik_smart\"\n" +
            "            },\n" +
            "            \"buildingNo\": {\n" +
            "                \"type\": \"keyword\",\n" +
            "                \"fields\": {\n" +
            "                    \"keyword\": {\n" +
            "                        \"type\": \"keyword\",\n" +
            "                        \"ignore_above\": 256\n" +
            "                    },\n" +
            "                    \"sort\": {\n" +
            "                        \"type\": \"icu_collation_keyword\",\n" +
            "                        \"index\": false,\n" +
            "                        \"numeric\": true\n" +
            "                    }\n" +
            "                }\n" +
            "            },\n" +
            "            \"checkCode\": {\n" +
            "                \"type\": \"text\",\n" +
            "                \"fields\": {\n" +
            "                    \"keyword\": {\n" +
            "                        \"type\": \"keyword\",\n" +
            "                        \"ignore_above\": 256\n" +
            "                    }\n" +
            "                }\n" +
            "            },\n" +
            "            \"checkCodeInDate\": {\n" +
            "                \"type\": \"date\"\n" +
            "            },\n" +
            "            \"city\": {\n" +
            "                \"type\": \"text\",\n" +
            "                \"fields\": {\n" +
            "                    \"keyword\": {\n" +
            "                        \"type\": \"keyword\",\n" +
            "                        \"ignore_above\": 256\n" +
            "                    }\n" +
            "                }\n" +
            "            },\n" +
            "            \"contractInfo\": {\n" +
            "                \"type\": \"text\",\n" +
            "                \"fields\": {\n" +
            "                    \"keyword\": {\n" +
            "                        \"type\": \"keyword\",\n" +
            "                        \"ignore_above\": 256\n" +
            "                    }\n" +
            "                }\n" +
            "            },\n" +
            "            \"createTime\": {\n" +
            "                \"type\": \"date\"\n" +
            "            },\n" +
            "            \"decoration\": {\n" +
            "                \"type\": \"text\",\n" +
            "                \"fields\": {\n" +
            "                    \"keyword\": {\n" +
            "                        \"type\": \"keyword\",\n" +
            "                        \"ignore_above\": 256\n" +
            "                    }\n" +
            "                }\n" +
            "            },\n" +
            "            \"deptId\": {\n" +
            "                \"type\": \"long\"\n" +
            "            },\n" +
            "            \"district\": {\n" +
            "                \"type\": \"text\",\n" +
            "                \"fields\": {\n" +
            "                    \"keyword\": {\n" +
            "                        \"type\": \"keyword\",\n" +
            "                        \"ignore_above\": 256\n" +
            "                    }\n" +
            "                },\n" +
            "                \"analyzer\": \"ik_max_word\",\n" +
            "                \"search_analyzer\": \"ik_smart\"\n" +
            "            },\n" +
            "            \"facetoType\": {\n" +
            "                \"type\": \"text\",\n" +
            "                \"fields\": {\n" +
            "                    \"keyword\": {\n" +
            "                        \"type\": \"keyword\",\n" +
            "                        \"ignore_above\": 256\n" +
            "                    }\n" +
            "                }\n" +
            "            },\n" +
            "            \"floorId\": {\n" +
            "                \"type\": \"long\"\n" +
            "            },\n" +
            "            \"floorNo\": {\n" +
            "                \"type\": \"long\"\n" +
            "            },\n" +
            "            \"floorSum\": {\n" +
            "                \"type\": \"long\"\n" +
            "            },\n" +
            "            \"fullName\": {\n" +
            "                \"type\": \"text\",\n" +
            "                \"fields\": {\n" +
            "                    \"keyword\": {\n" +
            "                        \"type\": \"keyword\",\n" +
            "                        \"ignore_above\": 256\n" +
            "                    }\n" +
            "                },\n" +
            "                \"analyzer\": \"ik_max_word\",\n" +
            "                \"search_analyzer\": \"ik_smart\"\n" +
            "            },\n" +
            "            \"houseNo\": {\n" +
            "                \"type\": \"text\",\n" +
            "                \"fields\": {\n" +
            "                    \"keyword\": {\n" +
            "                        \"type\": \"keyword\",\n" +
            "                        \"ignore_above\": 256\n" +
            "                    },\n" +
            "                    \"sort\": {\n" +
            "                        \"type\": \"icu_collation_keyword\",\n" +
            "                        \"index\": false,\n" +
            "                        \"numeric\": true\n" +
            "                    }\n" +
            "                }\n" +
            "            },\n" +
            "            \"houseState\": {\n" +
            "                \"type\": \"text\",\n" +
            "                \"fields\": {\n" +
            "                    \"keyword\": {\n" +
            "                        \"type\": \"keyword\",\n" +
            "                        \"ignore_above\": 256\n" +
            "                    }\n" +
            "                }\n" +
            "            },\n" +
            "            \"roomUsage\": {\n" +
            "                \"type\": \"text\",\n" +
            "                \"fields\": {\n" +
            "                    \"keyword\": {\n" +
            "                        \"type\": \"keyword\",\n" +
            "                        \"ignore_above\": 256\n" +
            "                    }\n" +
            "                }\n" +
            "            },\n" +
            "            \"id\": {\n" +
            "                \"type\": \"long\"\n" +
            "            },\n" +
            "            \"isConcentrated\": {\n" +
            "                \"type\": \"boolean\"\n" +
            "            },\n" +
            "            \"isLock\": {\n" +
            "                \"type\": \"boolean\"\n" +
            "            },\n" +
            "            \"isScheduled\": {\n" +
            "                \"type\": \"boolean\"\n" +
            "            },\n" +
            "            \"isWhole\": {\n" +
            "                \"type\": \"boolean\"\n" +
            "            },\n" +
            "            \"isStop\": {\n" +
            "                \"type\": \"boolean\"\n" +
            "            },\n" +
            "            \"isClean\": {\n" +
            "                \"type\": \"boolean\"\n" +
            "            },\n" +
            "            \"isRepair\": {\n" +
            "                \"type\": \"boolean\"\n" +
            "            },\n" +
            "            \"kitchenNum\": {\n" +
            "                \"type\": \"long\"\n" +
            "            },\n" +
            "            \"layoutId\": {\n" +
            "                \"type\": \"long\"\n" +
            "            },\n" +
            "            \"layoutName\": {\n" +
            "                \"type\": \"text\",\n" +
            "                \"fields\": {\n" +
            "                    \"keyword\": {\n" +
            "                        \"type\": \"keyword\",\n" +
            "                        \"ignore_above\": 256\n" +
            "                    }\n" +
            "                },\n" +
            "                \"analyzer\": \"ik_max_word\",\n" +
            "                \"search_analyzer\": \"ik_smart\"\n" +
            "            },\n" +
            "            \"livingroomNum\": {\n" +
            "                \"type\": \"long\"\n" +
            "            },\n" +
            "            \"preInfo\": {\n" +
            "                \"type\": \"text\",\n" +
            "                \"fields\": {\n" +
            "                    \"keyword\": {\n" +
            "                        \"type\": \"keyword\",\n" +
            "                        \"ignore_above\": 256\n" +
            "                    }\n" +
            "                }\n" +
            "            },\n" +
            "            \"price\": {\n" +
            "                \"type\": \"float\"\n" +
            "            },\n" +
            "            \"publicFacilities\": {\n" +
            "                \"type\": \"text\",\n" +
            "                \"fields\": {\n" +
            "                    \"keyword\": {\n" +
            "                        \"type\": \"keyword\",\n" +
            "                        \"ignore_above\": 256\n" +
            "                    }\n" +
            "                }\n" +
            "            },\n" +
            "            \"query\": {\n" +
            "                \"type\": \"text\",\n" +
            "                \"fields\": {\n" +
            "                    \"keyword\": {\n" +
            "                        \"type\": \"keyword\",\n" +
            "                        \"ignore_above\": 256\n" +
            "                    }\n" +
            "                }\n" +
            "            },\n" +
            "            \"residence\": {\n" +
            "                \"type\": \"text\",\n" +
            "                \"fields\": {\n" +
            "                    \"keyword\": {\n" +
            "                        \"type\": \"keyword\",\n" +
            "                        \"ignore_above\": 256\n" +
            "                    }\n" +
            "                }\n" +
            "            },\n" +
            "            \"roomAreaId\": {\n" +
            "                \"type\": \"long\"\n" +
            "            },\n" +
            "            \"roomHouseName\": {\n" +
            "                \"type\": \"text\",\n" +
            "                \"fields\": {\n" +
            "                    \"keyword\": {\n" +
            "                        \"type\": \"keyword\",\n" +
            "                        \"ignore_above\": 256\n" +
            "                    },\n" +
            "                    \"sort\": {\n" +
            "                        \"type\": \"icu_collation_keyword\",\n" +
            "                        \"index\": false,\n" +
            "                        \"numeric\": true\n" +
            "                    }\n" +
            "                },\n" +
            "                \"analyzer\": \"ik_max_word\",\n" +
            "                \"search_analyzer\": \"ik_smart\"\n" +
            "            },\n" +
            "            \"roomHouseNo\": {\n" +
            "                \"type\": \"text\",\n" +
            "                \"fields\": {\n" +
            "                    \"keyword\": {\n" +
            "                        \"type\": \"keyword\",\n" +
            "                        \"ignore_above\": 256\n" +
            "                    },\n" +
            "                    \"sort\": {\n" +
            "                        \"type\": \"icu_collation_keyword\",\n" +
            "                        \"index\": false,\n" +
            "                        \"numeric\": true\n" +
            "                    }\n" +
            "                },\n" +
            "                \"analyzer\": \"ik_max_word\",\n" +
            "                \"search_analyzer\": \"ik_smart\"\n" +
            "            },\n" +
            "            \"roomHouseTypeId\": {\n" +
            "                \"type\": \"long\"\n" +
            "            },\n" +
            "            \"roomHouseTypeName\": {\n" +
            "                \"type\": \"text\",\n" +
            "                \"fields\": {\n" +
            "                    \"keyword\": {\n" +
            "                        \"type\": \"keyword\",\n" +
            "                        \"ignore_above\": 256\n" +
            "                    }\n" +
            "                },\n" +
            "                \"analyzer\": \"ik_max_word\",\n" +
            "                \"search_analyzer\": \"ik_smart\"\n" +
            "            },\n" +
            "            \"roomType\": {\n" +
            "                \"type\": \"text\",\n" +
            "                \"fields\": {\n" +
            "                    \"keyword\": {\n" +
            "                        \"type\": \"keyword\",\n" +
            "                        \"ignore_above\": 256\n" +
            "                    }\n" +
            "                }\n" +
            "            },\n" +
            "            \"sourceType\": {\n" +
            "                \"type\": \"text\",\n" +
            "                \"fields\": {\n" +
            "                    \"keyword\": {\n" +
            "                        \"type\": \"keyword\",\n" +
            "                        \"ignore_above\": 256\n" +
            "                    }\n" +
            "                }\n" +
            "            },\n" +
            "            \"space\": {\n" +
            "                \"type\": \"float\"\n" +
            "            },\n" +
            "            \"street\": {\n" +
            "                \"type\": \"text\",\n" +
            "                \"fields\": {\n" +
            "                    \"keyword\": {\n" +
            "                        \"type\": \"keyword\",\n" +
            "                        \"ignore_above\": 256\n" +
            "                    }\n" +
            "                },\n" +
            "                \"analyzer\": \"ik_max_word\",\n" +
            "                \"search_analyzer\": \"ik_smart\"\n" +
            "            },\n" +
            "            \"superId\": {\n" +
            "                \"type\": \"long\"\n" +
            "            },\n" +
            "            \"tenantId\": {\n" +
            "                \"type\": \"long\"\n" +
            "            },\n" +
            "            \"tenantinfo\": {\n" +
            "                \"type\": \"text\",\n" +
            "                \"fields\": {\n" +
            "                    \"keyword\": {\n" +
            "                        \"type\": \"keyword\",\n" +
            "                        \"ignore_above\": 256\n" +
            "                    }\n" +
            "                },\n" +
            "                \"analyzer\": \"ik_max_word\",\n" +
            "                \"search_analyzer\": \"ik_smart\"\n" +
            "            },\n" +
            "            \"toiletNum\": {\n" +
            "                \"type\": \"long\"\n" +
            "            },\n" +
            "            \"toward\": {\n" +
            "                \"type\": \"text\",\n" +
            "                \"fields\": {\n" +
            "                    \"keyword\": {\n" +
            "                        \"type\": \"keyword\",\n" +
            "                        \"ignore_above\": 256\n" +
            "                    }\n" +
            "                }\n" +
            "            },\n" +
            "            \"unitNo\": {\n" +
            "                \"type\": \"text\",\n" +
            "                \"fields\": {\n" +
            "                    \"keyword\": {\n" +
            "                        \"type\": \"keyword\",\n" +
            "                        \"ignore_above\": 256\n" +
            "                    }\n" +
            "                }\n" +
            "            }\n" +
            "        }\n" +
            "}";

}
